package lumis.portal.dao.hibernate;

import lumis.portal.PortalException;
import lumis.portal.PortalObjectNotFoundException;
import lumis.portal.dao.DaoException;
import lumis.util.ITransaction;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

/**
 * Implements the generic CRUD data access operations using Hibernate APIs.
 * @since 4.0.11
 * @version $Revision: 7370 $ $Date: 2007-06-12 13:50:49 -0300 (Tue, 12 Jun 2007) $
 */
public abstract class GenericHibernateDao<T, ID extends Serializable>
{
    private Class<T> persistentClass;

    /**
     * Create a new DAO instance for beans of the specified class.
     * @param persistentClass the hibernate entity class.
     * @since 4.0.11
     */
    protected GenericHibernateDao(Class<T> persistentClass) 
    {
        this.persistentClass = persistentClass;
    }
    
    /**
     * Returns the class whose persistence this DAO controls. 
     * @since 4.0.11
     */
    protected Class<T> getPersistentClass() 
	{
        return persistentClass;
    }
    
    /**
     * Returns the hibernate session associated with the given transaction.
     * @param transaction the transaction.
     * @return the session.
     * @since 4.0.11
     */
    protected Session getSession(ITransaction transaction) throws PortalException
    {
		return ((ITransactionHibernate)transaction).getSession();
    }

    /**
     * Returns the bean with the given id.
     * @param id the bean's id.
	 * @param transaction the transaction for persistence access.
     * @return the bean.
     * @throws PortalObjectNotFoundException if the corresponding bean does not exist in the persistence.
     * @since 4.0.11
     */
	@SuppressWarnings("unchecked")
	public T get(ID id, ITransaction transaction) throws PortalObjectNotFoundException, PortalException
	{
		T bean = (T)getSession(transaction).get(getPersistentClass(), id);
		if (bean == null)
			throw new PortalObjectNotFoundException("STR_RESOURCE_NOT_FOUND;" + id);
		return bean;
	}

	/**
	 * Persists a transient bean, making it persistent. 
	 * @param bean the bean to be made persistent.
	 * @param transaction the transaction for persistence access.
	 * @throws PortalException
     * @since 4.0.11
	 */
	public void persist(T bean, ITransaction transaction) throws PortalException
	{
		getSession(transaction).persist(bean);
	}

	/**
	 * Deletes the given bean from persistence.
	 * @param bean the persistent bean.
	 * @param transaction the transaction for persistence access.
     * @since 4.0.11
	 */
	@SuppressWarnings("unchecked")
	public void delete(T bean, ITransaction transaction) throws PortalException
	{
		getSession(transaction).delete(bean);
	}
	
	/** 
	 * Utility find method for subclasses. 
     * @param transaction transaction for persistence access.
     * @param criterions criterions used to find the result.
     * @param orders specifies the order by which the results will be ordered.
     * @return a list with the beans found. 
     * @since 4.0.11
	 */
    @SuppressWarnings("unchecked")
	protected List<T> findByCriteria(ITransaction transaction, Criterion[] criterions, Order[] orders) throws DaoException
	{
		ITransactionHibernate txHib = (ITransactionHibernate)transaction;
		Session session = txHib.getSession();
        Criteria crit = session.createCriteria(getPersistentClass());
        if (criterions != null)
        {
            for (Criterion c : criterions) 
                crit.add(c);       	
        }
        if (orders != null)
        {
            for (Order order: orders)
            	crit.addOrder(order);
        }
        List<T> beans = crit.list();
        return beans;
   }

    /** 
     * Utility find method for subclasses.
     * @param transaction transaction for persistence access.
     * @param criterions criterions used to find the result.
     * @return a list with the beans found. 
     * @since 4.0.11
     */
    protected List<T> findByCriteria(ITransaction transaction, Criterion... criterions) throws DaoException
	{
    	return findByCriteria(transaction, criterions, null);
	}
}
